<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <p>{{ message }}</p>
        <p>{{ count }}</p>
        <p>{{ bool }}</p>
    </div>
</body>
<script>
    function MyVue(options){
        let {el,data,methods,computed,watch,} = options;

        var ele = document.querySelector(el); // 挂载的元素
        // 默认以挂载的元素作为 模板(重复使用)
        var html = ele.innerHTML; 
        // console.log(html);

        // 给data中的所有属性绑定取值拦截和赋值拦截 => 监听数据改变
        // Object.defineProperty(targetObj,key,desc)
        for(let key in data){
            let initValue = data[key]; // 存储初始值
            Object.defineProperty(data,key,{
                get:function(){  // 对data进行取值时 => 触发此拦截函数
                    return initValue;
                },
                set:function(val){   // 对data进赋值时  => 触发此拦截函数
                    console.log("监听到"+key+"发生改变");
                    initValue = val;
                    render();
                }
            })
        }


        // 给实例化对象绑定同名属性
        for(let key in data){ // 遍历data的所有属性
            Object.defineProperty(this,key,{
                get:function(){  // 对data进行取值时 => 触发此拦截函数
                    return data[key];
                },
                set:function(val){   // 对data进赋值时  => 触发此拦截函数
                    data[key] = val;
                }
            })
        }

        // 实例化对象中新增的属性
        this.$el = ele;
        this.$data = data;
        this.$optons = options;
        var _this = this;

        // 默认渲染 => 声明式渲染
        render();
        function render(){
            var reg = /\{\{(.+)\}\}/g;
            // console.log(reg.exec(html));
            // console.log(reg.exec(html));
            // console.log(reg.exec(html));
            // console.log(reg.exec(html)); // null

            var pattern = html;
            var result = null;
            while(result = reg.exec(pattern)){
                // console.log(result);
                var replaceStr = result[0];  // {{ message }}
                var matchStr = result[1].trim();  // message
                // console.log(matchStr);
                // pattern = pattern.replace(replaceStr,data[matchStr]);
                pattern = pattern.replace(replaceStr,_this[matchStr]);
            }
            // console.log(pattern);
            ele.innerHTML = pattern;
        }

    }

    var vm = new MyVue({
        el:"#app",
        data:{
            message:"hello world",
            count:100,
            bool:true,
        }
    })
    console.log(vm);

    setTimeout(()=>{
        // vm.$data.message = "Are you ok?"
        // vm.$data.count = 200;
        // vm.$data.bool = false;
        // console.log( vm.$data.message);

        // 实例化对象上绑定同属性  => 操作属性等价于操作 $data上同名属性
        vm.message = "Are you ok?"
        vm.count = 200;
        vm.bool = false;
    },2000)




</script>
</html>